package ie.dit.reg08.attSelector;

import ie.dit.reg08.manager.*;

import java.util.*;
/*
 * Uses a greedy search with no backtracking to construct a distinguishing description
 * Select next property to use based on which of the attributes not tested so far for 
 * inclusion in the description distinguishes the target from the most amount of 
 * remaining distractors
 * 
 * 
 */
public class Incremental2 implements greInterface {
	String id;
	boolean distinguishing;
	Hashtable description;
	Domain domain;
	TreeMap tmAttFreq;
	int totalCount;
	
	/*
	 * Note the boolean dummy variable that is passed into gre() is not used by the function.
	 * It is simply there to make the function signature match the interface defintion.
	 */
	public Incremental2(Trial t, TreeMap tm, int total, boolean includetype) {
		boolean dummy = true;
		id =  t.getID();		
		domain = t.getDomain();
		distinguishing = false;
		tmAttFreq = tm;
		totalCount = total;
		description = new Hashtable();
		description = gre(t, includetype, dummy);
	}
	
	public Hashtable getDescripton(){
		return description;
	}

	/*
	 * Note the boolean dummy variable that is passed into gre() is not used by the function.
	 * It is simply there to make the function signature match the interface defintion.
	 */
	public Hashtable gre(Trial t, boolean includetype, boolean dummy) {
		Vector vDistractors;
		Vector vPreviousProperties = new Vector();
		String sNextProperty;
		Entity target = t.getDomain().getTarget();
		Hashtable htTargetAttributes = target.getAttributes();
			
		Enumeration e = htTargetAttributes.keys();
		while (e.hasMoreElements()) {
							
			sNextProperty = mostDistinguishing(htTargetAttributes, vPreviousProperties, domain.distractorSet(description));
			vPreviousProperties.add(sNextProperty);

			
			//we don't need to check that the target has the property selected
			//as the distinguishing properties are selected from the target 
			//objects properties
				vDistractors = addAttribute(sNextProperty,
						(String) htTargetAttributes.get(sNextProperty));
				if (vDistractors.isEmpty()) {
					distinguishing = true;
					return description;
				}
		}
		return description;
	}
	
	public boolean isDistinguishing() {
		return distinguishing;
	}
	
	private Vector addAttribute(String nextProperty, String value) {
		int numdistractors = (domain.distractorSet(description)).size();
		description.put(nextProperty, value);
		if (numdistractors > domain.distractorSet(description).size()) {
			//ok leave the added attribute in the description
		} else {
			description.remove(nextProperty);
		}
		return domain.distractorSet(description);
	}

	/*
	 * Arg1 = a HashMap containing a the targets attributes (Strings) and values (Strings)
	 * Return value the attribute (String) that excludes the most distractors
	 * or null if there is a problem!
	 */
	public String mostDistinguishing(Hashtable ht, Vector vPrevious, Vector vDistractors) {
		String tmpA, tmpV;
		Entity ent;
		Hashtable htTmp;
		String mostDistinguishing = null;
		int maxExcluded = 0;
		int excluded;
		
		Iterator i;
		htTmp = new Hashtable();
		Enumeration e = ht.keys();
		while(e.hasMoreElements()) {
			excluded = 0;
			tmpA = (String)e.nextElement();	
			//don't consider properties that have already been checked for
			//inclusion in the description
			if(!vPrevious.contains(tmpA)) {
			
				tmpV = (String)ht.get(tmpA);
			
				htTmp.put(tmpA,tmpV);
				i = vDistractors.iterator();
			
				while(i.hasNext()) {
					ent = (Entity)i.next();
					if(!ent.isTarget()) {
						if(!ent.fulfills(htTmp)) {
							excluded++;
						}
					}
				}
				if(excluded > maxExcluded) {
					mostDistinguishing = tmpA;
				}
			}
			htTmp.remove(tmpA);
		}
		return mostDistinguishing;
	}
	
	public String getID() {
		return id;
	}
	
	public String xmlDescription() {  
		  String s = "<TRIAL ID=\"" + id + "\">\n";
		  s = s + "<DESCRIPTION>\n";
		  
		  Enumeration e = description.keys();
		  String k;
		  while(e.hasMoreElements()) {
			  k = (String)e.nextElement();
			  s = s + "<ATTRIBUTE NAME=\"" + k + "\" VALUE=\"" + description.get(k) + "\"/>\n";
		  }
		  s = s + "</DESCRIPTION>\n";
		  s = s + "</TRIAL>\n";
		  return s;
	}
}
